package com.cdy.jxc_project.controller;

import com.cdy.jxc_project.domain.TAdmin;
import com.cdy.jxc_project.domain.TSyslog;
import com.cdy.jxc_project.service.SyslogService;
import com.cdy.jxc_project.utils.AddSysLog;
import com.cdy.jxc_project.utils.SessionKey;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.CompletableFuture;

/**
 * @describe 系统日志  切面处理类
 * @author zj
 * @date 2020 2020/10/13 15:23
 */
@Slf4j
@Aspect
@Component
public class SysLogAspect {
    @Resource
    private SyslogService syslogService;
    //日志扫描包,aop检查那些地方使用这个注解，就会生效
    //com.hqyj.server.*.*(..)

    @Pointcut("@annotation(com.cdy.jxc_project.utils.AddSysLog)")
    public void sysLogPointCut() {
    }
    //  增强类型
    @Around("sysLogPointCut()")
//  5种 前置增强，后置增强，异常增强， 最终增强，环绕 final
    //5s-10s
    public  Object around(ProceedingJoinPoint point) throws Throwable {
        //开始时间
        long beginTime = System.currentTimeMillis();
        //执行目标方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //设置IP地址
        //获取ip地址 //这个RequestContextHolder是Springmvc提供来获得请求的东西，登录的时候统计
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
        //获取ip地址
        String ip = request.getRemoteAddr();
        //保存日志
        CompletableFuture.runAsync(() -> saveSysLog(point, time, ip)) ;
        return result;
    }
    /**
     * 保存日志
     * @param joinPoint
     * @param time
     */
    private void saveSysLog(ProceedingJoinPoint joinPoint, long time,  String ip) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        TSyslog sysLog = new TSyslog();
        sysLog.setIp(ip);
//      通过反射获取日志信息
        AddSysLog addSysLog = method.getAnnotation(AddSysLog.class);
        if (addSysLog != null) {
            //注解上的描述
            sysLog.setOperation(addSysLog.value());
        }
        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()");
        //请求的参数
        Object[] args = joinPoint.getArgs();
        try {
            sysLog.setParams(args.toString());


            //获取admin信息
            TAdmin admin = (TAdmin) SecurityUtils.getSubject().getSession().getAttribute(SessionKey.adminKey);
            //获取是哪一个账号操作的
            sysLog.setUserName(admin.getUsername());
            //用时多少
            sysLog.setTime(Integer.parseInt(time+""));
            sysLog.setCreateTime(new Date());//创建时间
            //保存系统日志
            if (addSysLog.intoDB()) {
//               执行方法的保存
                syslogService.save(sysLog);
            }
        } catch (Exception ignored) {
            log.error(ignored.getMessage());
        }
    }
}

